#include "udp.h"

int main(int argc, char** argv)
{
    	short port;			// Eigene Port
    	short rport;			//Port den anzusprechen Socket

	int shmid; 			// Filedescriptor des Shared Memory
    	int sphid; 			// Filedescriptor des Semaphor

    	struct sockaddr_in raddr; 	// Adress des Host
    	struct hostent *hostinfo;	// HostInfo
    	SharedMem *mem;			// Zeiger auf der Schared Memory
    
	if(argc != 4)
	{
		printf("udp port rhostname rport\n");
		exit(1);
	}

	/// Ports einlesen
    	port = atoi(argv[1]);
    	rport = atoi(argv[3]);
   
	if(0 > (hostinfo = gethostbyname(argv[2])))
	{
		perror("Problem with gethostbyname()");
		exit(1);
	}

	signal(SIGTERM, signalhandler);
	signal(SIGINT, signalhandler);
	//Socket erzeugen
	sockN = getSocket(port);
	//sharedMemory
	shmid = getSharedMemory(SHM_KEY, (IPC_CREAT|SHM_PERM), sizeof(SharedMem));
	//semahphore
	sphid = getSemaphor(SEM_KEY, SEM_NUM, (IPC_CREAT|SEM_PERM));
	initSemaphor(sphid, 0, 1);
	// Adress des Host initialisieren
	memset((void *)&raddr, 0, sizeof(raddr));
	raddr.sin_family = AF_INET;
	raddr.sin_port = htons(rport);
	memcpy(&raddr.sin_addr.s_addr, hostinfo->h_addr, hostinfo->h_length); 
	
	// Shared Memory in den Adress Raum einfuegen 
	if ( 0 > ( mem = shmat(shmid, 0, 0) ) ) {
	perror(" problem with shmat()");
	exit(1);
	}
	// init
	initSharedMemory(mem, sizeof(SharedMem));
	int pid = fork();

	/** Nachrichten schicken **/
	if(pid)
    	{
		char toSend[100];
	
		srandom(time(NULL) + getpid());
		int itemNummer = 0;
		while(1)
		{
			// Paket initialisieren
			memset(toSend, 0, 100);
			sprintf(toSend, "ITEM%d", itemNummer++);
		
			// Versuchen zu schicken
			if(0 > sendto(sockN, toSend, strlen(toSend), 0, 
				(struct sockaddr* )&raddr, 
				sizeof(raddr)))
			{
				perror("Problem with send()");
				exit(1);
			}
			
			// gesendeten Paket in Shared Memory(in puffer fuer gesendeten Daten) kopieren
			// 
			down(sphid, 0);
			strcpy(&(mem->ouPuffer[mem->ouWdx][0]),toSend);
			printf("i am %d send: %s\n", getpid(), &(mem->ouPuffer[mem->ouWdx][0]));
			mem->ouWdx = (mem->ouWdx+1)%BUFFER_SIZE; // Write Index nach vorn bewegen
			up(sphid, 0);
			
			//Random warten
			sleep(random()%10);
		}
    	}
	/** Nachrichten bekommen **/
    	else
    	{
		char item[4000];// Puffer fuer empfangen Nachrichten
		int length = sizeof(raddr);
		while(1)
		{
			// Warten auf Nachrichten
			if(0 > recvfrom(sockN, item, 4000, 0, 
				(struct sockaddr *)&raddr, &length))
			{
				perror("Problem recvfrom()");
				exit(1);
			}
			// Empfangenen Nachrichten in Shared Memory(in Puffer fuer empfangenen Daten) kopieren
			down(sphid, 0);
			strcpy(&(mem->inPuffer[mem->inWdx][0]),	item);
			printf("\ti am %d, i receive: %s\n", getpid(), &(mem->inPuffer[mem->inWdx][0]));
			mem->inWdx = (mem->inWdx+1)%BUFFER_SIZE; // Write Index Bewegen
			up(sphid, 0);
		}
    	}
	return 0;
}
